/* 初始化通用同步异步收发器：USART */
    .equ RCC_APB2ENR, 0x40021018
    .equ USART0_CR1, 
    .equ USART0_CR2,
    .equ USART0_BRR,
    .equ USART0_TDR,
    .equ USART0_SR, 0x40013800

    .text
    .global init_usart0
    .global stop_TX
    .global putc_usart0
    .global deinit_usart0

    .thumb
    .arch armv7-m
    .syntax unified

init_usart0:
    /* 初始化 usart0 */
    /* 使用默认停止位位数：1位 */
    /* 系统CLK假设是默认的8MHz */
    /* 波特率选择： */
    push {r0, r1, r2} //必须用 bl 指令调用
    ldr r0, =RCC_APB2ENR
    mov r1, #0x1
    lsl r1, #14 //usart0
    add r1, #0x4 //GPIOA
    ldr r2, [r0]
    orr r1, r2 //读-改-写，可能存在竞争冒险
    str r1, [r0] //使能 usart0 以及 GPIOA 时钟
    //初始化时一般会做一次复位
    ldr r0, =USART0_CR1
    str , [r0] //置位UE，编程M位定义字长
    ldr r0, =USART0_CR2
    str , [r0] //编程停止位的位数，默认：1位
    ldr r0, =USART0_BRR
    str , [r0] //选择波特率
    ldr r0, =USART0_CR1
    str , [r0] //置位TE，发送空闲帧
    pop {r0, r1, r2}
    bx lr

stop_TX:
    /* 停止发送（清除TE位） */
    push {r0, r1, r2}
    ldr r0, =USART0_SR
    mov r1, #
wait_TC1:
    ldr r2, [r0]
     //检查TC是否置位，读SR的动作本身会清除 TC 位
    bnz wait_TC1
    ldr r0, =USART0_CR1
    str , [r0] //清除TE位
    pop {r0, r1, r2}
    bx lr

deinit_usart0:
    /* 去初始化 usart0 */
    /* 清除UE位，并关闭时钟 */
    push {r0, r1, r2}
    ldr r0, =USART0_SR
    mov r2, #
wait_TC2:
    ldr r1, [R0]
    and r2, r1 //检查TC是否置位
    bnz wait_TC2
    ldr r0, =USART0_CR1
    str , [r0] //清除UE
     //关闭 usart0 时钟
    pop {r0, r1, r2}
    bx lr

putc_usart0:
    /* 该子程序通过UART发送一个字符 */
    /* 入口条件： R0 = 要发送的字符 */
    push {r1, r2} /* 保存寄存器 */
    ldr r1, =USART0_SR
putcwaitloop:
    ldr r2, [r1] /* 获取状态位TXE */
    tst.w r2, #0x20 /* 检查发送缓冲区满标志 */
    bne putcwaitloop /* 如果已满则循环等待 */
    ldr r1, =USART0_TDR /* 否则继续往发送缓冲区里送数据 */
    str r0, [r1]
    //mov r0, #1 // r0 保存返回值
    pop {r1, r2}
    bx lr    
    .end
